package cn.com.cifi.mars.util;

import cn.com.cifi.mars.bean.vo.price.PriceReportVO;
import cn.com.cifi.mars.constant.OrgTypeEunm;
import cn.com.cifi.mars.constant.VersionTypeEunm;
import cn.com.cifi.mars.entity.DmDmValueReport;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;

import java.lang.reflect.Field;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 因大量计算，校验，组织数据的代码太多，因此抽出
 */
@Slf4j
public class PriceReportUtils {


    /**
     * 从源数据中组织数据，组织成具有层级关系的分组数据
     * @param dmDmValueReportList 原始数据
     * @return
     */
    public static List<PriceReportVO> calcPriceReport(List<DmDmValueReport> dmDmValueReportList) {
        //生成ID 父ID map
        Map<String, String[]> parentIdMap = makeParentIdMap(dmDmValueReportList);

        Map<String,Map<String,PriceReportVO>> areaSectionMap = new HashMap<>();
        Map<String,Map<String,PriceReportVO>> buildingVOMap = new HashMap<>();

        //1、面积段层级计算，面积段汇总至楼栋。
        //2、没有面积段的楼栋单独计算
        makeBaseReportVOMap(dmDmValueReportList, parentIdMap, areaSectionMap, buildingVOMap);

        //楼栋汇总到产品构成
        Map<String,Map<String,PriceReportVO>> productVOMap = new HashMap<>();
        calcParent(parentIdMap,buildingVOMap,productVOMap);

        //产品构成到组团
        Map<String,Map<String,PriceReportVO>> groupMap = new HashMap<>();
        calcParent(parentIdMap, productVOMap, groupMap);

        //组团到分期
        Map<String,Map<String,PriceReportVO>> projectfMap = new HashMap<>();
        calcParent(parentIdMap, groupMap, projectfMap);

        //分期层级加入货值版本名称
        projectfMap.values().stream().flatMap(x->x.values().stream()).forEach(x->{
            dmDmValueReportList.stream().filter(y->x.getOrgId().equals(y.getProjectfId())).findFirst().ifPresent(y->{
                x.setVersionName(y.getVersionName()+"-"+y.getVersionUpdateTime().format(DateTimeFormatter.ofPattern("yyyyMMdd")) + (VersionTypeEunm.INVESTMENT.getKey().equals(y.getVersionType()) && 1 == y.getIsAssessmentVersion()?"（考核版）":""));
                x.setVersionType(y.getVersionType());
            });
        });


        //分期到项目
        Map<String,Map<String,PriceReportVO>> projectMap = new HashMap<>();
        calcParent(parentIdMap, projectfMap, projectMap);

        return BeanConvertUtils.toPriceReportVOList(projectMap, projectfMap, groupMap, productVOMap, buildingVOMap, areaSectionMap);
    }

    /**
     * 计算面积段、楼栋数据，这部门作为基础数据可以向上级汇总，产生高层级的数据
     * @param dmDmValueReportList
     * @param parentIdMap
     * @param areaSectionMap
     * @param buildingVOMap
     */
    public static void makeBaseReportVOMap(List<DmDmValueReport> dmDmValueReportList, Map<String, String[]> parentIdMap, Map<String, Map<String, PriceReportVO>> areaSectionMap, Map<String, Map<String, PriceReportVO>> buildingVOMap) {
        //面积段
        List<DmDmValueReport> areaSectionList = dmDmValueReportList.stream().filter(x -> StringUtils.isNotBlank(x.getMiniGranularityName())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(areaSectionList)){
            areaSectionList.stream()
                    .map(areaSection -> BeanConvertUtils.toPriceReportVOMap(areaSection, areaSection.getMiniGranularityId(), areaSection.getMiniGranularityName(),areaSection.getBuildingId(), OrgTypeEunm.ORG_HOUSE_PACKAGE.getKey()))
                    .flatMap(map->map.entrySet().stream())
                    .forEach(entry->{
                        areaSectionMap.put(entry.getKey(),entry.getValue());
                    });
            //面积段汇总至楼栋
            calcParent(parentIdMap,areaSectionMap,buildingVOMap);
        }


        //楼栋拆分、与面积段汇总的楼栋合并
        List<DmDmValueReport> buildingList = dmDmValueReportList.stream().filter(x -> StringUtils.isNotBlank(x.getBuildingId()) && StringUtils.isBlank(x.getMiniGranularityName())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(buildingList)){
            buildingList.stream().map(building -> {
                String[] parent = parentIdMap.get(building.getBuildingId());
                return BeanConvertUtils.toPriceReportVOMap(building, building.getBuildingId(), building.getBuildingName(),parent[0], OrgTypeEunm.ORG_BUILD.getKey());
            }).flatMap(x->x.entrySet().stream()).forEach(entry->{
                buildingVOMap.put(entry.getKey(),entry.getValue());
            });
        }
    }

    /**
     * 制作一个可以查询父级ID名称信息的Map，遍于检索
     * @param dmDmValueReportList
     * @return
     */
    public static Map<String, String[]> makeParentIdMap(List<DmDmValueReport> dmDmValueReportList) {
        Map<String,String[]> parentIdMap = new HashMap<>();
        dmDmValueReportList.stream().forEach(dmDmValueReport -> {
            if (StringUtils.isNotBlank(dmDmValueReport.getMiniGranularityId()) && !parentIdMap.containsKey(dmDmValueReport.getMiniGranularityId())){
                parentIdMap.put(dmDmValueReport.getMiniGranularityId(),new String[]{dmDmValueReport.getBuildingId(), dmDmValueReport.getBuildingName(), OrgTypeEunm.ORG_BUILD.getKey()});
            }
            String productId = DigestUtils.md5Hex(dmDmValueReport.getProjectfId() + dmDmValueReport.getGroupCode() + dmDmValueReport.getProductTypeCode() + dmDmValueReport.getProductCode());
            if (!parentIdMap.containsKey(dmDmValueReport.getBuildingId())){
                parentIdMap.put(dmDmValueReport.getBuildingId(),new String[]{productId,dmDmValueReport.getProductName(),OrgTypeEunm.ORG_PRODUCT.getKey()});
            }
            if (!parentIdMap.containsKey(productId)){
                parentIdMap.put(productId,new String[]{dmDmValueReport.getGroupId(),dmDmValueReport.getGroupName(),OrgTypeEunm.ORG_GROUP.getKey()});
            }
            if (!parentIdMap.containsKey(dmDmValueReport.getGroupId())){
                parentIdMap.put(dmDmValueReport.getGroupId(),new String[]{dmDmValueReport.getProjectfId(),dmDmValueReport.getProjectfName(),OrgTypeEunm.ORG_STAGE.getKey()});
            }
            if (!parentIdMap.containsKey(dmDmValueReport.getProjectfId())){
                parentIdMap.put(dmDmValueReport.getProjectfId(),new String[]{dmDmValueReport.getProjectId(),dmDmValueReport.getProjectName(),OrgTypeEunm.ORG_PRODUCTF.getKey()});
            }
            if (!parentIdMap.containsKey(dmDmValueReport.getProjectId())){
                parentIdMap.put(dmDmValueReport.getProjectId(),new String[]{"","",""});
            }
        });
        return parentIdMap;
    }

    /**
     * 低级数据向高层级数据汇总
     * @param parentIdMap
     * @param sonMap
     * @param parentMap
     */
    public static void calcParent(Map<String, String[]> parentIdMap, Map<String, Map<String, PriceReportVO>> sonMap, Map<String, Map<String, PriceReportVO>> parentMap) {
        sonMap.entrySet().stream().forEach(entry->{
            String[] parentArr = parentIdMap.get(entry.getKey());
            Map<String, PriceReportVO> parentVOMap = parentMap.get(parentArr[0]);
            if (parentVOMap == null){
                parentVOMap = new HashMap<>();
                parentMap.put(parentArr[0],parentVOMap);
            }
            Map<String, PriceReportVO> sonVOMap = entry.getValue();
            Map<String, PriceReportVO> finalParentVOMap = parentVOMap;
            sonVOMap.entrySet().stream().forEach(voEntry->{
                PriceReportVO parentVO = finalParentVOMap.get(voEntry.getKey());
                PriceReportVO sonVO = voEntry.getValue();
                if (parentVO == null){
                    parentVO = new PriceReportVO();
                    String[] parent = parentIdMap.get(sonVO.getOrgId());
                    String[] parent2 = parentIdMap.get(sonVO.getParentOrgId());
                    parentVO.setGroupCode(sonVO.getGroupCode());
                    parentVO.setGroupName(sonVO.getGroupName());
                    parentVO.setOrgId(parent[0]);
                    parentVO.setOrgName(parent[1]);
                    parentVO.setOrgType(parent[2]);
                    parentVO.setParentOrgId(parent2[0]);
                    if (OrgTypeEunm.ORG_NOT_SALE_PACKAGE.getKey().equals(sonVO.getOrgType())
                            ||OrgTypeEunm.ORG_NOT_SALING_PARKING.getKey().equals(sonVO.getOrgType())
                            ||OrgTypeEunm.ORG_SALE_PACKAGE.getKey().equals(sonVO.getOrgType())
                            ||OrgTypeEunm.ORG_HOUSE_PACKAGE.getKey().equals(sonVO.getOrgType())
                            ||OrgTypeEunm.ORG_BUILD.getKey().equals(sonVO.getOrgType())){
                        parentVO.setIsParking(sonVO.getIsParking());
                    }
                    finalParentVOMap.put(sonVO.getGroupCode(),parentVO);
                }
                sonVO.addToParent(parentVO);
            });
        });
    }


    /**
     * 将Map转换为有序的list
     * @param resultMap
     * @return
     */
    public static List<Map<String, Object>> toSortedList(Map<String, Map<String, Object>> resultMap) {
        return resultMap.values().parallelStream().sorted((a, b) -> {
            DmDmValueReport aRef = (DmDmValueReport) a.get("ref");
            DmDmValueReport bRef = (DmDmValueReport) b.get("ref");

                /*String aProjectName = StrUtils.nvl(aRef.getProjectName());
                String bProjectName = StrUtils.nvl(bRef.getProjectName());
                if (!aProjectName.equals(bProjectName)) {
                    return aProjectName.compareTo(bProjectName);
                }*/

            String aStageName = StrUtils.nvl(aRef.getProjectfName());
            String bStageName = StrUtils.nvl(bRef.getProjectfName());

            if (!aStageName.equals(bStageName)) {
                return ReportUtils.compareStrStartedChinaNum(aStageName,bStageName);
            }

            String aGroupName = StrUtils.nvl(aRef.getGroupName());
            String bGroupName = StrUtils.nvl(bRef.getGroupName());
            if (!aGroupName.equals(bGroupName)) {
                return ReportUtils.compareStrStartedChinaNum(aGroupName,bGroupName);
            }

                /*String aProductTypeName = StrUtils.nvl(aRef.getProductTypeName());
                String bProductTypeName = StrUtils.nvl(bRef.getProductTypeName());
                if (!aProductTypeName.equals(bProductTypeName)) {
                    return aProductTypeName.compareTo(bProductTypeName);
                }*/

            String aProductName = StrUtils.nvl(aRef.getProductName());
            String bProductName = StrUtils.nvl(bRef.getProductName());
            if (!aProductName.equals(bProductName)) {
                return aProductName.compareTo(bProductName);
            }

            String aBuildingName = StrUtils.nvl(aRef.getBuildingName());
            String bBuildingName = StrUtils.nvl(bRef.getBuildingName());
            if (!aBuildingName.equals(bBuildingName)) {
                return ReportUtils.compareStrStartedChinaNum(aBuildingName,bBuildingName);
            }

            String aAreaSectionName = StrUtils.nvl(aRef.getMiniGranularityName());
            String bAreaSectionName = StrUtils.nvl(bRef.getMiniGranularityName());
            if (!aAreaSectionName.equals(bAreaSectionName)) {
                return aAreaSectionName.compareTo(bAreaSectionName);
            }
            return 0;
        }).collect(Collectors.toList());
    }

    /**
     * 将分组平行的list数据，依据id合并为一条数据
     * @param list
     * @param dmDmValueReportList
     * @return
     */
    public static Map<String, Map<String, Object>> mergeGroupMap(List<PriceReportVO> list, List<DmDmValueReport> dmDmValueReportList) {
        Map<String,Map<String,Object>> resultMap = new HashMap<>();
        list.stream().forEach(x -> {
            Map<String, Object> entity = resultMap.get(x.getOrgId());
            if (entity == null){
                entity = new HashMap<>();
                resultMap.put(x.getOrgId(),entity);
            }
            //处理关联对象
            Object ref = entity.get("ref");
            Map<String, Object> finalEntity = entity;
            if (ref == null){
                //将组织机构抽出存储，用于后面排序
                OrgTypeEunm orgTypeEunm = OrgTypeEunm.getByKey(x.getOrgType());
                if (orgTypeEunm != null){
                    entity.put("orgType",orgTypeEunm);
                    switch (orgTypeEunm){
                        case ORG_PRODUCTF:
                            dmDmValueReportList.stream().findFirst().ifPresent(dmDmValueReport -> {
                                DmDmValueReport dest = new DmDmValueReport();
                                try {
                                    PropertyUtils.copyProperties(dest,dmDmValueReport);
                                    //排序用
                                    dest.setProjectfName("");
                                    finalEntity.put("ref",dest);
                                } catch (Exception e) {
                                    log.error(e.getMessage(),e);
                                }
                            });
                            break;
                        case ORG_STAGE:
                            dmDmValueReportList.stream().filter(dmDmValueReport -> dmDmValueReport.getProjectfId().equals(x.getOrgId())).findFirst().ifPresent(dmDmValueReport -> {
                                DmDmValueReport dest = new DmDmValueReport();
                                try {
                                    PropertyUtils.copyProperties(dest,dmDmValueReport);
                                    //排序用
                                    dest.setGroupName("");
                                    finalEntity.put("ref",dest);
                                } catch (Exception e) {
                                    log.error(e.getMessage(),e);
                                }
                            });
                            break;
                        case ORG_GROUP:
                            dmDmValueReportList.stream().filter(dmDmValueReport -> dmDmValueReport.getGroupId().equals(x.getOrgId())).findFirst().ifPresent(dmDmValueReport -> {
                                DmDmValueReport dest = new DmDmValueReport();
                                try {
                                    PropertyUtils.copyProperties(dest,dmDmValueReport);
                                    //排序用
                                    dest.setProductName("");
                                    finalEntity.put("ref",dest);
                                } catch (Exception e) {
                                    log.error(e.getMessage(),e);
                                }
                            });
                            break;
                        /*case ORG_PRO_TYPE:
                            dmDmValueReportList.stream().filter(dmDmValueReport -> {
                                String productTypeId = DigestUtils.md5Hex(dmDmValueReport.getProjectfId() + dmDmValueReport.getGroupCode() + dmDmValueReport.getProductTypeCode());
                                return productTypeId.equals(x.getOrgId());
                            }).findFirst().ifPresent(dmDmValueReport -> {
                                DmDmValueReport dest = new DmDmValueReport();
                                try {
                                    PropertyUtils.copyProperties(dest,dmDmValueReport);
                                    //排序用
                                    dest.setProductName("");
                                    finalEntity.put("ref",dest);
                                } catch (Exception e) {
                                    log.error(e.getMessage(),e);
                                }
                            });
                            break;*/
                        case ORG_PRODUCT:
                            dmDmValueReportList.stream().filter(dmDmValueReport -> {
                                String productId = DigestUtils.md5Hex(dmDmValueReport.getProjectfId() + dmDmValueReport.getGroupCode() + dmDmValueReport.getProductTypeCode()+dmDmValueReport.getProductCode());
                                return productId.equals(x.getOrgId());
                            }).findFirst().ifPresent(dmDmValueReport ->{
                                DmDmValueReport dest = new DmDmValueReport();
                                try {
                                    PropertyUtils.copyProperties(dest,dmDmValueReport);
                                    //排序用
                                    dest.setBuildingName("");
                                    finalEntity.put("ref",dest);
                                } catch (Exception e) {
                                    log.error(e.getMessage(),e);
                                }
                            });
                            break;
                        case ORG_BUILD:
                            dmDmValueReportList.stream().filter(dmDmValueReport -> dmDmValueReport.getBuildingId().equals(x.getOrgId())).findFirst().ifPresent(dmDmValueReport -> {
                                DmDmValueReport dest = new DmDmValueReport();
                                try {
                                    PropertyUtils.copyProperties(dest,dmDmValueReport);
                                    //排序用
                                    dest.setMiniGranularityName("");
                                    finalEntity.put("ref",dest);
                                } catch (Exception e) {
                                    log.error(e.getMessage(),e);
                                }
                            });
                            break;
                        default:
                            //面积段与面积段相同层级的比如可售车位统一叫面积段
                            dmDmValueReportList.stream().filter(dmDmValueReport -> x.getOrgId().equals(dmDmValueReport.getMiniGranularityId())).findFirst().ifPresent(dmDmValueReport -> finalEntity.put("ref",dmDmValueReport));
                    }
                }
            }

            Field[] declaredFields = x.getClass().getDeclaredFields();
            for (Field declaredField : declaredFields) {
                declaredField.setAccessible(true);
                String key = x.getGroupCode() + "=>"+declaredField.getName();;
                try {
                    entity.put(key, ReportUtils.toString(declaredField.get(x)));
                } catch (Exception e) {
                    entity.put(key,"");
                }
            }
        });
        return resultMap;
    }
}
